
package de.justphil.tcg.tcgandroidclient.gui;

import de.justphil.tcg.tcgandroidclient.R;
import de.justphil.tcg.tcgandroidclient.Storage;
import de.justphil.tcg.tcgandroidclient.content.rest.RESTCreateGameResponse;
import de.justphil.tcg.tcgandroidclient.content.rest.RESTJoinMsgData;
import de.justphil.tcg.tcgandroidclient.content.rest.RESTGameReadyResponse;
import de.justphil.tcg.tcgandroidclient.gui.gameboard.GameBoardAct;
import de.justphil.tcg.tcgandroidclient.network.rest.RESTMessengerService;
import de.justphil.tcg.tcgandroidclient.util.StringTools;
import de.justphil.tcg.tcgandroidclient.util.TCGLog;
import android.app.Activity;
import android.app.ProgressDialog;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.ServiceConnection;
import android.os.Bundle;
import android.os.Handler;
import android.os.IBinder;
import android.os.Message;
import android.os.Messenger;
import android.os.RemoteException;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;

public class PlayAct extends Activity {
	
	public static final String EXTRA_DECK_ID = "deckId";
	private Button createButton;
	private Button joinButton;
	private Button autoButton;
	private EditText otpEditText;
	private long deckId;
	private ProgressDialog createDialog;
	private Messenger restMessenger;
	private Messenger messenger;
	private boolean bound;
	/**
	 * Class for interacting with the main interface of the service.
	 */
	private ServiceConnection connection = new ServiceConnection() {
		
		public void onServiceConnected(ComponentName className, IBinder binder) {
		
			restMessenger = ((RESTMessengerService.RESTBinder) binder).getMessenger(messenger);
			bound = true;
		}
		
		public void onServiceDisconnected(ComponentName className) {
		
			restMessenger = null;
			bound = false;
		}
	};
	
	@Override
	public void onCreate(Bundle savedInstanceState) {
	
		super.onCreate(savedInstanceState);
		setContentView(R.layout.play);
		messenger = new Messenger(new Handler() {
			
			@Override
			public void handleMessage(Message msg) {
			
				PlayAct.this.handleMessage(msg);
			}
		});
		initializeComponents();
	}
	
	@Override
	protected void onResume() {
	
		super.onResume();
		deckId = getIntent().getLongExtra(EXTRA_DECK_ID, 0);
		if (deckId == 0) {
			throw new IllegalStateException("The deckId must not be null!");
		}
	}
	
	@Override
	protected void onStart() {
	
		super.onStart();
		// Bind to the service
		if (!bindService(new Intent(this, RESTMessengerService.class), connection,
				Context.BIND_AUTO_CREATE)) {
			throw new IllegalStateException("Thread binding failed!");
		}
	}
	
	@Override
	protected void onStop() {
	
		super.onStop();
		// Unbind from the service
		if (bound) {
			unbindService(connection);
			bound = false;
		}
	}
	
	private void handleMessage(Message msg) {
	
		switch (msg.what) {
			case RESTMessengerService.MSG_CREATED:
				handleCreatedMsg((RESTCreateGameResponse) msg.obj);
				break;
			case RESTMessengerService.MSG_JOINED:
				handleJoinedMsg((RESTGameReadyResponse) msg.obj);
				break;
			case RESTMessengerService.MSG_ERROR:
				handleErrorMsg(msg.arg1, (String) msg.obj);
				break;
			case RESTMessengerService.MSG_NOT_RESPONDING:
				handleNotRespondingMsg();
				break;
			default:
				throw new IllegalArgumentException("Message type unknown!");
		}
	}
	
	private void handleNotRespondingMsg() {
	
		ProgressDialog d = getDialog();
		if (d.isShowing()) {
			d.dismiss();
		}
		Toast.makeText(this, "The REST server is not responding!", Toast.LENGTH_LONG).show();
	}
	
	private void handleErrorMsg(int code, String message) {
	
		ProgressDialog d = getDialog();
		if (d.isShowing()) {
			d.dismiss();
		}
		String text = StringTools.getString(new Object[] {
				"Error response ", code, ": ", message });
		Toast.makeText(this, text, Toast.LENGTH_LONG).show();
		TCGLog.w(new Object[] {
			text });
	}
	
	private void handleJoinedMsg(RESTGameReadyResponse response) {
	
		TCGLog.i(new Object[] {
			"Game Joined." });
		getDialog().dismiss();
		Intent intent = new Intent(PlayAct.this, GameBoardAct.class);
		intent.putExtra(GameBoardAct.EXTRA_GAME_ID, response.getGameId());
		intent.putExtra(GameBoardAct.EXTRA_OTP, response.getPlayerOtp());
		Storage.setWebSocketServer(response.getWsUri());
		startActivity(intent);
	}
	
	private void handleCreatedMsg(RESTCreateGameResponse result) {
	
		TCGLog.i(new Object[] {
			"Game Created!" });
		getDialog().setMessage(
				"Game Password: " + result.getOtp() + "\n" + "Waiting for opponent...");
	}
	
	private ProgressDialog getDialog() {
	
		if (createDialog == null) {
			createDialog = new ProgressDialog(this);
		}
		return createDialog;
	}
	
	private void requestCreateGame() {
	
		if (!bound) {
			throw new IllegalStateException("Thread is not bound!");
		}
		TCGLog.d(new Object[] {
			"Initiating game creation." });
		ProgressDialog d = getDialog();
		d.setMessage("Creating game with Deck " + deckId + "...");
		d.show();
		Message msg = Message.obtain(null, RESTMessengerService.MSG_CREATE, deckId);
		try {
			restMessenger.send(msg);
		}
		catch (RemoteException e) {
			throw new RuntimeException("Could not send message: " + e.getMessage());
		}
	}
	
	private void initializeComponents() {
	
		createButton = (Button) findViewById(R.id.play_button_create);
		joinButton = (Button) findViewById(R.id.play_button_join);
		autoButton = (Button) findViewById(R.id.play_button_auto);
		otpEditText = (EditText) findViewById(R.id.play_editText_otp);
		createButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
			
				requestCreateGame();
			}
		});
		joinButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
			
				requestJoinGame();
				// startActivity(new Intent(PlayAct.this, GameBoardAct.class));
			}
		});
	}
	
	private void requestJoinGame() {
	
		String otp = otpEditText.getText().toString();
		if (!bound) {
			throw new IllegalStateException("Thread is not bound!");
		}
		TCGLog.d(new Object[] {
			"Initiating game join." });
		ProgressDialog d = getDialog();
		d.setMessage("Joining game with Deck " + deckId + "\n" + "and password " + otp + "...");
		d.show();
		Message msg =
				Message.obtain(null, RESTMessengerService.MSG_JOIN,
						new RESTJoinMsgData(deckId, otp));
		try {
			restMessenger.send(msg);
		}
		catch (RemoteException e) {
			throw new RuntimeException("Could not send message: " + e.getMessage());
		}
	}
}
